package com.liang.blog.gateway.filter;

import com.alibaba.fastjson.JSONObject;
import com.liang.blog.common.exception.BlogException;
import com.liang.blog.common.result.Result;
import com.liang.blog.common.result.ResultCodeEnum;
import com.liang.blog.model.constant.CacheConstants;
import com.liang.blog.model.constant.SecurityConstants;
import com.liang.blog.redis.service.RedisService;
import com.liang.blog.service.util.TokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;

/**
 * @Author：YanWenLiang
 * @Date:2023-08-19-20:06
 */
@Component
public class AuthGlobalFilter implements GlobalFilter, Ordered {
    private AntPathMatcher antPathMatcher = new AntPathMatcher();

    @Autowired
    private RedisService redisService;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        ServerHttpRequest.Builder mutate = request.mutate();

        String[] paths = {"/**/verifyCode/**","/**/login", "/**/register",
                "/**/sendRegisterEmail/**", "/**/setLoginIp/**",
                "/**/getUserCount/**", "/**/saveUser", "/**/dict/**", "/**/user/getUserById/**",
                "/**/article/public/**", "/**/sendLoginEmail/**", "/**/emailLogin",
                "/**/user/public/**"};

        String path = request.getURI().getPath();

        for (String pathNow : paths) {
            if (antPathMatcher.match(pathNow, path)){
                return chain.filter(exchange);
            }
        }

        String token = this.getToken(request);
        if (null == token || "".equals(token)){
            return out(response, ResultCodeEnum.TOKEN_NULL);
        }

        Long userId = TokenUtil.getUserId(token);
        String account = TokenUtil.getAccount(token);
        String userKey = TokenUtil.getUserKey(token);


        boolean islogin = redisService.hasKey(CacheConstants.LOGIN_TOKEN_KEY + userKey);
        if (!islogin)
        {
            return out(response, ResultCodeEnum.LOGIN_EXPIRED);
        }

        if (StringUtils.isEmpty(userId) || StringUtils.isEmpty(account) || StringUtils.isEmpty(userKey))
        {
            return out(response, ResultCodeEnum.TOKEN_ERROR);
        }

        // 添加请求头
        mutate.header(SecurityConstants.DETAILS_USER_ID, String.valueOf(userId));
        mutate.header(SecurityConstants.DETAILS_ACCOUNT, account);
        mutate.header(SecurityConstants.USER_KEY, userKey);
        return chain.filter(exchange);
    }

    /**
     * 接口鉴权失败返回数据
     * @param response
     * @return
     */
    private Mono<Void> out(ServerHttpResponse response, ResultCodeEnum resultCodeEnum) {
        Result result = Result.build(null, resultCodeEnum);
        byte[] bits = JSONObject.toJSONString(result).getBytes(StandardCharsets.UTF_8);
        DataBuffer buffer = response.bufferFactory().wrap(bits);
        //指定编码，否则在浏览器中会中文乱码
        response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        return response.writeWith(Mono.just(buffer));
    }

    /**
     * 获取 token
     * @param request
     * @return
     */
    public String getToken(ServerHttpRequest request){
        return request.getHeaders().getFirst("token");
    }




    @Override
    public int getOrder() {
        return 0;
    }
}
